package com.tpvlog.dfs.datanode.resgiter;

import com.tpvlog.dfs.datanode.file.DataNodeInfo;
import com.tpvlog.dfs.datanode.file.StorageManager;
import com.tpvlog.dfs.datanode.server.NameNodeRpcClient;
import com.tpvlog.dfs.rpc.service.HeartbeatResponse;
import com.tpvlog.dfs.rpc.service.RegisterResponse;

/**
 * Data的服务注册和心跳管理组件
 *
 * @author Ressmix
 */
public class LeaseManager {

    // 首次注册成功
    public static final Integer REGISTER_FIRST_SUCCESS = 10000;

    // 已经注册过
    public static final Integer REGISTER_EXIST = 10001;

    // 首次心跳(还没注册)
    public static final Integer RENEW_FIRST = 10003;

    // 已经存在且心跳成功
    public static final Integer RENEW_SUCCESS = 10004;

    private NameNodeRpcClient rpcClient;

    private StorageManager storageManager;

    public LeaseManager(NameNodeRpcClient rpcClient, StorageManager storageManager) {
        this.rpcClient = rpcClient;
        this.storageManager = storageManager;
    }

    public Boolean register() {
        RegisterResponse response = rpcClient.register();
        if (response.getStatus() == REGISTER_FIRST_SUCCESS) {
            // 首次注册成功
            System.out.println("首次注册成功，需要全量上报存储信息......");
            DataNodeInfo dataNodeInfo = storageManager.getStorageInfo();
            rpcClient.fullyReportDataNodeInfo(dataNodeInfo);
            return true;
        } else {
            // 节点已经存在不能重复注册
            System.out.println("节点已注册，不需要全量上报存储信息......");
            return false;
        }
    }

    public void heartbeat() {
        new HeartbeatThread().start();
    }

    /**
     * 负责心跳的线程
     */
    private class HeartbeatThread extends Thread {
        @Override
        public void run() {
            while (true) {
                try {
                    // 发送心跳
                    HeartbeatResponse response = rpcClient.heartbeat();
                    if (response.getStatus() == RENEW_FIRST) {
                        //心跳失败，节点还没注册
                        register();
                    }
                    Thread.sleep(30 * 1000);
                } catch (Exception e) {
                    System.out.println("当前NameNode不可用，心跳失败.......");
                }
            }
        }
    }
}
